﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using WeiTap.Validator;

namespace WeiTap.Validator.Internal
{
    public class PropertyChain
    {
        readonly List<string> memberNames = new List<string>();
        public PropertyChain()
        {

        }
        public PropertyChain(IEnumerable<string> memberNames)
        {
            this.memberNames.AddRange(memberNames);
        }
        public PropertyChain(PropertyChain parent)
        {
            if (parent != null)
                this.memberNames.AddRange(parent.memberNames);
        }
        public static PropertyChain FromExpression(LambdaExpression express)
        {

            var memberNames = new Stack<string>();
            var getMemberExp = new Func<Expression, MemberExpression>(toUnwarp =>
            {
                if (toUnwarp is UnaryExpression)
                    return ((UnaryExpression)toUnwarp).Operand as MemberExpression;
                return toUnwarp as MemberExpression;
            });
            var memberExp = getMemberExp(express.Body);
            while (memberExp != null)
            {
                memberNames.Push(memberExp.Member.Name);
                memberExp = getMemberExp(memberExp.Expression);
            }
            return new PropertyChain(memberNames);
        }
        public void Add(MemberInfo member)
        {
            if (member != null)
                memberNames.Add(member.Name);
        }
        public void Add(string propertyName)
        {
            if (!string.IsNullOrEmpty(propertyName))
                memberNames.Add(propertyName);
        }
        public void AddIndexer(object indexer)
        {
            if (memberNames.Count == 0)
                throw new InvalidOperationException("不能对空的属性链执行此操作");
            string last = memberNames[memberNames.Count - 1];
            last += "[" + indexer + "]";
            memberNames[memberNames.Count - 1] = last;
        }
        public override string ToString()
        {
            return string.Join(ValidatorOptions.ProperyChainSeparator, memberNames);
        }
        public bool IsChildChainOf(PropertyChain chain)
        {
            return ToString().StartsWith(chain.ToString());
        }
        public string BuildPropertyName(string propertyName)
        {
            var chain = new PropertyChain(this);
            chain.Add(propertyName);
            return chain.ToString();
        }
        public int Count
        {
            get { return memberNames.Count; }
        }
    }
}
